package com.mojian.service.impl;

import com.mojian.service.RecommendationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 推荐系统服务实现类
 * 基于实际的数据库数据进行个性化推荐
 */
@Service
@Primary
@RequiredArgsConstructor
@Slf4j
public class RecommendationServiceImpl implements RecommendationService {

    private final JdbcTemplate jdbcTemplate;

    @Override
    public Map<String, Object> getPersonalizedRecommendations(Long userId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("获取用户[{}]的个性化推荐", userId);
            
            // 未登录用户或游客(userId=0)，返回通用推荐
            if (userId == 0) {
                return getGenericRecommendations();
            }
            
            // 1. 获取用户常看标签
            List<Map<String, Object>> favoriteTags = getUserFavoriteTags(userId);
            
            // 2. 获取基于标签的推荐
            List<Map<String, Object>> tagBasedRecommendations = new ArrayList<>();
            if (!favoriteTags.isEmpty()) {
                tagBasedRecommendations = getTagBasedRecommendations(userId, favoriteTags);
            }
            
            // 3. 获取用户常看的文章
            List<Map<String, Object>> frequentArticles = getUserFrequentArticles(userId);
            
            // 4. 获取基于文章相似度的推荐
            List<Map<String, Object>> similarArticleRecommendations = new ArrayList<>();
            if (!frequentArticles.isEmpty()) {
                similarArticleRecommendations = getSimilarArticleRecommendations(userId, frequentArticles);
            }
            
            // 5. 合并并去重推荐结果
            Set<Long> recommendedIds = new HashSet<>();
            List<Map<String, Object>> finalRecommendations = new ArrayList<>();
            
            // 添加基于标签的推荐
            addUniqueRecommendations(tagBasedRecommendations, finalRecommendations, recommendedIds, 5);
            
            // 添加基于相似文章的推荐
            addUniqueRecommendations(similarArticleRecommendations, finalRecommendations, recommendedIds, 5);
            
            // 如果推荐数量不足，添加热门文章
            if (finalRecommendations.size() < 6) {
                List<Map<String, Object>> popularArticles = getPopularArticles(6 - finalRecommendations.size());
                addUniqueRecommendations(popularArticles, finalRecommendations, recommendedIds, 6 - finalRecommendations.size());
            }
            
            // 6. 组装结果
            result.put("recommendations", finalRecommendations);
            result.put("favoriteTags", favoriteTags.subList(0, Math.min(favoriteTags.size(), 3)));
            
            if (finalRecommendations.isEmpty()) {
                result.put("fallback", true);
                result.put("recommendations", getPopularArticles(6));
            }
            
        } catch (Exception e) {
            log.error("生成个性化推荐失败", e);
            
            // 如果出错，返回热门文章作为备选
            try {
                result.put("recommendations", getPopularArticles(6));
                result.put("fallback", true);
            } catch (Exception ex) {
                log.error("获取热门文章失败", ex);
                result.put("recommendations", new ArrayList<>());
                result.put("error", "生成个性化推荐失败: " + e.getMessage());
            }
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> getUserBrowsingAnalysis(Long userId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("获取用户[{}]的浏览数据分析", userId);
            
            // 1. 用户常看标签统计
            List<Map<String, Object>> tagStats = jdbcTemplate.queryForList(
                "SELECT t.id, t.name, uft.view_count as count " +
                "FROM sys_user_frequent_tag uft " +
                "JOIN sys_tag t ON uft.tag_id = t.id " +
                "WHERE uft.user_id = ? " +
                "ORDER BY uft.view_count DESC " +
                "LIMIT 10",
                userId
            );
            
            // 2. 用户常看文章统计
            List<Map<String, Object>> articleStats = jdbcTemplate.queryForList(
                "SELECT a.id, a.title, ufa.view_count as count, a.cover " +
                "FROM sys_user_frequent_article ufa " +
                "JOIN sys_article a ON ufa.article_id = a.id " +
                "WHERE ufa.user_id = ? " +
                "ORDER BY ufa.view_count DESC " +
                "LIMIT 5",
                userId
            );
            
            // 3. 文章浏览类别统计
            List<Map<String, Object>> categoryStats = jdbcTemplate.queryForList(
                "SELECT c.id, c.name, COUNT(*) as count " +
                "FROM sys_user_article_view uav " +
                "JOIN sys_article a ON uav.article_id = a.id " +
                "JOIN sys_category c ON a.category_id = c.id " +
                "WHERE uav.user_id = ? " +
                "GROUP BY c.id, c.name " +
                "ORDER BY count DESC " +
                "LIMIT 5",
                userId
            );
            
            // 4. 总浏览数
            Integer totalViews = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM sys_user_article_view WHERE user_id = ?",
                Integer.class,
                userId
            );
            
            // 5. 阅读时间分析
            // 总阅读时长(秒)
            Integer totalReadTime = jdbcTemplate.queryForObject(
                "SELECT COALESCE(SUM(read_time), 0) FROM sys_user_article_view WHERE user_id = ?",
                Integer.class,
                userId
            );
            
            // 平均阅读时长(秒)
            Double avgReadTime = 0.0;
            if (totalViews != null && totalViews > 0) {
                avgReadTime = totalReadTime / (double) totalViews;
            }
            
            // 阅读时间分布
            Map<String, Object> timeAnalysis = new HashMap<>();
            timeAnalysis.put("totalReadTime", totalReadTime);  // 总阅读时间(秒)
            timeAnalysis.put("totalReadMinutes", Math.round(totalReadTime / 60.0)); // 总阅读时间(分钟)
            timeAnalysis.put("avgReadTime", avgReadTime);  // 平均阅读时间(秒)
            timeAnalysis.put("avgReadMinutes", Math.round(avgReadTime / 60.0 * 10) / 10.0); // 平均阅读时间(分钟)，保留一位小数
            
            // 获取最长阅读时间
            Integer maxReadTime = jdbcTemplate.queryForObject(
                "SELECT COALESCE(MAX(read_time), 0) FROM sys_user_article_view WHERE user_id = ?",
                Integer.class, 
                userId
            );
            timeAnalysis.put("maxReadTime", maxReadTime);  // 最长阅读时间(秒)
            timeAnalysis.put("maxReadMinutes", Math.round(maxReadTime / 60.0)); // 最长阅读时间(分钟)
            
            // 组装结果
            result.put("favoriteTags", tagStats);
            result.put("frequentArticles", articleStats);
            result.put("categoryStats", categoryStats);
            result.put("totalViews", totalViews != null ? totalViews : 0);
            result.put("timeAnalysis", timeAnalysis);
            
            // 添加阅读频次分析（按天统计）
            List<Map<String, Object>> readingTrends = jdbcTemplate.queryForList(
                "SELECT DATE(create_time) as date, COUNT(*) as count " +
                "FROM sys_user_article_view " +
                "WHERE user_id = ? " +
                "GROUP BY DATE(create_time) " +
                "ORDER BY date DESC " +
                "LIMIT 7", 
                userId
            );
            result.put("readingTrends", readingTrends);
            
        } catch (Exception e) {
            log.error("生成用户浏览分析失败", e);
            result.put("error", "生成用户浏览分析失败: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 获取用户常看的标签
     */
    private List<Map<String, Object>> getUserFavoriteTags(Long userId) {
        String sql = 
            "SELECT t.id, t.name, uft.view_count " +
            "FROM sys_user_frequent_tag uft " +
            "JOIN sys_tag t ON uft.tag_id = t.id " +
            "WHERE uft.user_id = ? " +
            "ORDER BY uft.view_count DESC";
        
        return jdbcTemplate.queryForList(sql, userId);
    }
    
    /**
     * 获取用户常看的文章
     */
    private List<Map<String, Object>> getUserFrequentArticles(Long userId) {
        String sql = 
            "SELECT a.id, a.title, a.category_id, ufa.view_count " +
            "FROM sys_user_frequent_article ufa " +
            "JOIN sys_article a ON ufa.article_id = a.id " +
            "WHERE ufa.user_id = ? " +
            "ORDER BY ufa.view_count DESC";
        
        return jdbcTemplate.queryForList(sql, userId);
    }
    
    /**
     * 基于标签的推荐
     */
    private List<Map<String, Object>> getTagBasedRecommendations(Long userId, List<Map<String, Object>> favoriteTags) {
        if (favoriteTags.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 提取用户最喜欢的前3个标签ID
        StringBuilder tagIdBuilder = new StringBuilder();
        for (int i = 0; i < Math.min(favoriteTags.size(), 3); i++) {
            if (i > 0) tagIdBuilder.append(",");
            tagIdBuilder.append(favoriteTags.get(i).get("id"));
        }
        String tagIds = tagIdBuilder.toString();
        
        // 如果没有有效的标签ID，返回空列表
        if (tagIds.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 查询包含这些标签的、用户未浏览过的文章
        String sql = 
            "SELECT a.id, a.title, a.summary, a.cover, a.create_time as createTime, c.name as categoryName " +
            "FROM sys_article a " +
            "JOIN sys_article_tag at ON a.id = at.article_id " +
            "JOIN sys_category c ON a.category_id = c.id " +
            "WHERE at.tag_id IN (" + tagIds + ") " +
            "AND a.status = 1 " +
            "AND a.id NOT IN (SELECT DISTINCT article_id FROM sys_user_article_view WHERE user_id = ?) " +
            "ORDER BY a.create_time DESC " +
            "LIMIT 10";
        
        return jdbcTemplate.queryForList(sql, userId);
    }
    
    /**
     * 基于文章相似度的推荐
     */
    private List<Map<String, Object>> getSimilarArticleRecommendations(Long userId, List<Map<String, Object>> frequentArticles) {
        if (frequentArticles.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 提取用户最常看的前3篇文章的分类ID
        StringBuilder categoryIdBuilder = new StringBuilder();
        for (int i = 0; i < Math.min(frequentArticles.size(), 3); i++) {
            if (i > 0) categoryIdBuilder.append(",");
            categoryIdBuilder.append(frequentArticles.get(i).get("category_id"));
        }
        String categoryIds = categoryIdBuilder.toString();
        
        // 如果没有有效的分类ID，返回空列表
        if (categoryIds.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 查询同分类下的、用户未浏览过的文章
        String sql = 
            "SELECT a.id, a.title, a.summary, a.cover, a.create_time as createTime, c.name as categoryName " +
            "FROM sys_article a " +
            "JOIN sys_category c ON a.category_id = c.id " +
            "WHERE a.category_id IN (" + categoryIds + ") " +
            "AND a.status = 1 " +
            "AND a.id NOT IN (SELECT DISTINCT article_id FROM sys_user_article_view WHERE user_id = ?) " +
            "ORDER BY a.create_time DESC " +
            "LIMIT 10";
        
        return jdbcTemplate.queryForList(sql, userId);
    }
    
    /**
     * 获取热门文章
     */
    private List<Map<String, Object>> getPopularArticles(int limit) {
        String sql = 
            "SELECT a.id, a.title, a.summary, a.cover, a.create_time as createTime, c.name as categoryName " +
            "FROM sys_article a " +
            "JOIN sys_category c ON a.category_id = c.id " +
            "WHERE a.status = 1 " +
            "ORDER BY a.create_time DESC " +
            "LIMIT ?";
        
        return jdbcTemplate.queryForList(sql, limit);
    }
    
    /**
     * 添加唯一的推荐文章（避免重复）
     */
    private void addUniqueRecommendations(
            List<Map<String, Object>> source, 
            List<Map<String, Object>> target, 
            Set<Long> existingIds, 
            int maxToAdd) {
        
        int added = 0;
        for (Map<String, Object> article : source) {
            Long id = ((Number) article.get("id")).longValue();
            if (!existingIds.contains(id) && added < maxToAdd) {
                target.add(article);
                existingIds.add(id);
                added++;
            }
        }
    }
    
    /**
     * 获取通用推荐（未登录用户）
     */
    private Map<String, Object> getGenericRecommendations() {
        Map<String, Object> result = new HashMap<>();
        try {
            log.info("获取通用推荐");
            
            // 获取最新文章作为推荐
            List<Map<String, Object>> newestArticles = getNewestArticles(6);
            result.put("recommendations", newestArticles);
            result.put("isGeneric", true);
            
        } catch (Exception e) {
            log.error("获取通用推荐失败", e);
            result.put("recommendations", new ArrayList<>());
            result.put("error", "获取通用推荐失败: " + e.getMessage());
        }
        return result;
    }
    
    /**
     * 获取最新文章
     */
    private List<Map<String, Object>> getNewestArticles(int limit) {
        String sql = 
            "SELECT a.id, a.title, a.summary, a.cover, a.create_time as createTime, c.name as categoryName " +
            "FROM sys_article a " +
            "JOIN sys_category c ON a.category_id = c.id " +
            "WHERE a.status = 1 " +
            "ORDER BY a.create_time DESC " +
            "LIMIT ?";
        
        return jdbcTemplate.queryForList(sql, limit);
    }
} 